/*
 * Copyright (c) 2006-2019, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2019-11-09     xiangxistu   first version
 * 2020-05-18     chenyaxing   modify usart3 remap check
 */

#include "stdlib.h"
#include "drv_usart.h"
#include "stdio.h"
#include "string.h"
#include "rtconfig.h"

#define DBG_TAG              "drv.usart"

#ifdef DRV_DEBUG
#define DBG_LVL               DBG_LOG
#else
#define DBG_LVL               DBG_INFO
#endif

#include <rtdbg.h>

static UART_HandleTypeDef uart_handle_debug; // UART1
UART_HandleTypeDef uart_handle_co2;   // UART2
UART_HandleTypeDef uart_handle_cat1; // UART3


void MX_USART1_UART_Init(void)
{

  uart_handle_debug.Instance = USART1;
  uart_handle_debug.Init.BaudRate = 115200;
  uart_handle_debug.Init.WordLength = UART_WORDLENGTH_8B;
  uart_handle_debug.Init.StopBits = UART_STOPBITS_1;
  uart_handle_debug.Init.Parity = UART_PARITY_NONE;
  uart_handle_debug.Init.Mode = UART_MODE_TX_RX;
  uart_handle_debug.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  uart_handle_debug.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&uart_handle_debug) != HAL_OK)
  {
    Error_Handler();
  }

}

void MX_USART2_UART_Init(void)
{
  uart_handle_co2.Instance = USART2;
  uart_handle_co2.Init.BaudRate = 115200;
  uart_handle_co2.Init.WordLength = UART_WORDLENGTH_8B;
  uart_handle_co2.Init.StopBits = UART_STOPBITS_1;
  uart_handle_co2.Init.Parity = UART_PARITY_NONE;
  uart_handle_co2.Init.Mode = UART_MODE_TX_RX;
  uart_handle_co2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  uart_handle_co2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&uart_handle_co2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USART3 init function */

void MX_USART3_UART_Init(void)
{

  uart_handle_cat1.Instance = USART3;
  uart_handle_cat1.Init.BaudRate = 115200;
  uart_handle_cat1.Init.WordLength = UART_WORDLENGTH_8B;
  uart_handle_cat1.Init.StopBits = UART_STOPBITS_1;
  uart_handle_cat1.Init.Parity = UART_PARITY_NONE;
  uart_handle_cat1.Init.Mode = UART_MODE_TX_RX;
  uart_handle_cat1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  uart_handle_cat1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&uart_handle_cat1) != HAL_OK)
  {
    Error_Handler();
  }

}

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN USART1_MspInit 1 */

  /* USER CODE END USART1_MspInit 1 */
  }else if(uartHandle->Instance==USART2)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA2     ------> USART1_TX
    PA3     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART2_IRQn);
  /* USER CODE BEGIN USART1_MspInit 1 */

  /* USER CODE END USART1_MspInit 1 */
  }
  else if(uartHandle->Instance==USART3)
  {
  /* USER CODE BEGIN USART3_MspInit 0 */

  /* USER CODE END USART3_MspInit 0 */
    /* USART3 clock enable */
    __HAL_RCC_USART3_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**USART3 GPIO Configuration
    PB10     ------> USART3_TX
    PB11     ------> USART3_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* USART3 interrupt Init */
    HAL_NVIC_SetPriority(USART3_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART3_IRQn);
  /* USER CODE BEGIN USART3_MspInit 1 */
	
  /* USER CODE END USART3_MspInit 1 */
  }
}

void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
  if(uartHandle->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspDeInit 0 */

  /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

  /* USER CODE BEGIN USART1_MspDeInit 1 */

  /* USER CODE END USART1_MspDeInit 1 */
  }else if(uartHandle->Instance==USART2)
  {
  /* USER CODE BEGIN USART1_MspDeInit 0 */

  /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);

	/* USART2 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART2_IRQn);
  /* USER CODE BEGIN USART1_MspDeInit 1 */

  /* USER CODE END USART1_MspDeInit 1 */
  }else if(uartHandle->Instance==USART3)
  {
  /* USER CODE BEGIN USART3_MspDeInit 0 */

  /* USER CODE END USART3_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART3_CLK_DISABLE();

    /**USART3 GPIO Configuration
    PB10     ------> USART3_TX
    PB11     ------> USART3_RX
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11);

    /* USART3 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USART3_IRQn);
  /* USER CODE BEGIN USART3_MspDeInit 1 */

  /* USER CODE END USART3_MspDeInit 1 */
  }
}


int drv_usart_init(int index)
{
    UART_HandleTypeDef *husart;
    if (0 == index)
    {
        MX_USART1_UART_Init();
    }else if (1 == index) {
        MX_USART2_UART_Init();
    }else if (2 == index) {
        MX_USART3_UART_Init();
    }

    return RT_EOK;
}

int drv_usart_send_bytes(int index, uint8_t *data, uint8_t len)
{
    UART_HandleTypeDef *husart;
	int i = 0;
		
    if (0 == index)
    {
        husart = &uart_handle_debug;
    }
    else if (1 == index)
    {
        husart = &uart_handle_co2;
    }else if (2 == index) {
        husart = &uart_handle_cat1;
    }
	
	for (i = 0; i < len ; i++)
	{
		HAL_UART_Transmit(husart, (data + i), 1, 10);
	}
	
    return 0;
}

int drv_usart_recv_bytes(int index, uint8_t *data, uint8_t len)
{
    UART_HandleTypeDef *husart;

    if (0 == index)
    {
        husart = &uart_handle_debug;
    }
    else if (1 == index)
    {
        husart = &uart_handle_co2;
    }else if (2 == index) {
        husart = &uart_handle_cat1;
    }

    return HAL_UART_Receive(husart, data, len, 10);
}

int drv_usart_recv_bytes_IT(int index, uint8_t *data, uint8_t len)
{
    UART_HandleTypeDef *husart;

    if (0 == index)
    {
        husart = &uart_handle_debug;
    }
    else if (1 == index)
    {
        husart = &uart_handle_co2;
    }else if (2 == index) {
        husart = &uart_handle_cat1;
    }

    return HAL_UART_Receive_IT(husart, data, len);
}


#ifdef RT_USING_CONSOLE

int rt_hw_usart_init(void)
{
    drv_usart_init(0);

    return RT_EOK;
}
INIT_BOARD_EXPORT(rt_hw_usart_init);

void rt_hw_console_output(const char *str)
{
    rt_size_t i = 0, size = 0;
    char a = '\r';

    size = rt_strlen(str);
    for (i = 0; i < size; i++)
    {
        if (*(str + i) == '\n')
        {
//            HAL_UART_Transmit(&uart_handle_debug, (uint8_t *)&a, 1, 1);
			drv_usart_send_bytes(0, (uint8_t *)&a, 1);
        }
//        HAL_UART_Transmit(&uart_handle_debug, (uint8_t *)(str + i), 1, 1);
		drv_usart_send_bytes(0, (uint8_t *)(str + i), 1);
    }
}
	
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&uart_handle_debug, (uint8_t *)&ch, 1, 0xFFFF);
  return ch;
}

#ifdef RT_USING_FINSH
char rt_hw_console_getchar(void)
{
    uint8_t ch = 0;

    if (__HAL_UART_GET_FLAG(&uart_handle_debug, UART_FLAG_RXNE) != RESET)
    {
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32F0) \
    || defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32H7) \
    || defined(SOC_SERIES_STM32G4)
        ch = uart_handle_debug.Instance->RDR & 0xff;
#else
		drv_usart_recv_bytes(0, &ch,1);
#endif
    }
    else
    {
        if(__HAL_UART_GET_FLAG(&uart_handle_debug, UART_FLAG_ORE) != RESET)
        {
            __HAL_UART_CLEAR_OREFLAG(&uart_handle_debug);
        }
        rt_thread_mdelay(10);
    }
    return ch;
}
#endif /* RT_USING_FINSH */
#endif /* RT_USING_CONSLONE */


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
